#include "stdafx.h"
#include "afxtempl.h"

#include "resource.h"
#include "global.h"
#include "IsismarcView.h"
#include "stdlib.h"		// for atoi()
#include  "zoom.h"
#include "conversion.h"
//#include "xmalloc.h"
#include "MainFrm.h"
#include "MyIsisMarcZ.h"
#include "mensaje.h"



#include "stdafx.h"



//detalles en global.h


long IsisApp;

bool primera;
CString n_perfil;
CString cip_lang;
CString cip_data;
CString cip_menu;
CString cip_msg;
CString cip_servers;
CString cip_gizmod;
CString cip_intervalz;
CString cip_proxy;
CString cip_db;
CString cip_user;
CString cip_mensaje;
int cip_update;
CString cip_help;
CString cip_log;
CString cip_perfil;
CString cip_towin;
CString cip_fromwin;
CString cip_1001;
CString cip_1002;
CString cip_1003;
CString cip_1004;
CString cip_1005;
CString cip_marc21sub;
CString cip_marc21field;
CString cip_marc21end;
CString cip_repetible;
CString cip_serveraddress;
CString cip_serverport;

CString este_dir;
CString root;

CString gcip_dbisis;
CString gcip_manual; 
CArray <cdg, cdg&> gcip_code;
int gcip_ldr;
CString gcip_wkst;
CString gcip_proc;
CString gcip_autonum;
CString gcip_autoprefix;
CString gcip_dots;
CString gcip_leader5;
CString gcip_leader6;
CString gcip_leader7;
CString gcip_leader17;
CString gcip_leader18;


CArray <CString, CString &> gcip_formats;
CArray <destino, destino&> gcolaDestinos;

bool copia = false;
bool all;
bool cerro_ok;
bool cambio_titulo;
bool threadfin = false;
bool thread_ejecucion = false;
bool zona_critica_1 = false;



CString DevolverFechaIso()
{
	SYSTEMTIME st;
	CString devuelvo,cadena;

	GetLocalTime(&st);
	devuelvo="";
	cadena.Format("%4u",st.wYear);
	devuelvo+=cadena;
	cadena.Format("%02u",st.wMonth);
	devuelvo+=cadena;
	cadena.Format("%02u",st.wDay);
	devuelvo+=cadena;
	cadena.Format("%02u",st.wHour);
	devuelvo+=cadena;
	cadena.Format("%02u",st.wMinute);
	devuelvo+=cadena;
	cadena.Format("%02u",st.wSecond);
	devuelvo+=cadena;

	return devuelvo;
}

CString FechaHoraLegible()
{
	SYSTEMTIME st;
	CString devuelvo,cadena;

	GetLocalTime(&st);
	devuelvo="";
	cadena.Format("%4u",st.wYear);
	devuelvo+=cadena;
	cadena.Format("%02u",st.wMonth);
	devuelvo+="-"+cadena;
	cadena.Format("%02u",st.wDay);
	devuelvo+="-"+cadena;
	cadena.Format("%02u",st.wHour);
	devuelvo+=" "+cadena;
	cadena.Format("%02u",st.wMinute);
	devuelvo+=":"+cadena;
	cadena.Format("%02u",st.wSecond);
	devuelvo+=":"+cadena;

	return devuelvo;
}


void Log(CString mensaje1,CString mensaje2,CMyIsisMarcZ* cme,CString searchcode)
{
	long mfn;
	CString miArea;

	zona_critica_1=true;
	if (mensaje2.GetLength()>0)
		miArea = "<1>"+searchcode+"</1><2>"+DevolverFechaIso()+"</2><3>"+mensaje1+":"+mensaje2+"</3>"+"<4>"+searchcode+"</4>";		
	else
		miArea = "<1>"+searchcode+"</1><2>"+DevolverFechaIso()+"</2><3>"+mensaje1+"</3>"+"<4>"+searchcode+"</4>";


	mfn = cme->IsisRegistroNuevo(miArea,true);
	zona_critica_1=false;	
	
}

void AbrirBases(CMyIsisMarcZ* cmi, CMyIsisMarcZ* cme, CMyIsisMarcZ* cmz)
{
		
	// Apertura de resultados
	CFileFind f;

	CString mytemp = cmi->DevolverUbicacion()+"zrecs.mst";
	if( !f.FindFile(mytemp))
	{		
		cmi->IsisNuevo(mytemp,FALSE);
	}
	cmi->IsisIniciarRegistro(mytemp);
	cmi->IsisAbrirInvertido(cmi->DevolverUbicacion()+"zrecs","1 0 v9010^a");


	// Apertura del log
	mytemp = cme->DevolverUbicacion()+"logZ3950.mst";
	if( !f.FindFile(mytemp))
	{		
		cme->IsisNuevo(mytemp,FALSE);
	}
	cme->IsisIniciarRegistro(mytemp);
	cme->IsisAbrirInvertido(cme->DevolverUbicacion()+"logZ3950","1 0 v1");


	// Apertura de Busquedas
	mytemp = cmz->DevolverUbicacion()+"zsearchs.mst";
	if( !f.FindFile(mytemp))
	{		
		cmz->IsisNuevo(mytemp,FALSE);
	}
	cmz->IsisIniciarRegistro(mytemp);
	
}

void CerrarBases(CMyIsisMarcZ* cmi, CMyIsisMarcZ* cme, CMyIsisMarcZ* cmz)
{
	cme->IsisFin();
	cmi->IsisFin();
	cmz->IsisFin();	

}

void ActualizarInvertido(CMyIsisMarcZ* cmi, CMyIsisMarcZ* cme)
{
	zona_critica_1=true;
	if (cmi->IsisCantRegistros()>0)
		cmi->IsisUpdInvertido(1,cmi->IsisCantRegistros());

	if (cme->IsisCantRegistros()>0)
		cme->IsisUpdInvertido(1,cme->IsisCantRegistros());
	zona_critica_1=false;
}

bool ProcesoBusqueda(CString host, CString port, CString databaseName, CString PQNExpression, int limite, CString searchcode, CString nametarget,CMyIsisMarcZ* cmi,CMyIsisMarcZ* cme, bool isUTF)
{

	void* tabla = "";
	const char* mensaje,*addinfo;
	char miArea[MAXMFRL];
	CMyIsisMarcZ cmt;

	CString mytemp = cmt.DevolverUbicacion()+"ztemp.mst";
	cmt.IsisNuevo(mytemp,FALSE);
	if (cip_gizmod!="")
		cmt.IsisAbrirGizmo();
		

	ZOOM_connection z;
    ZOOM_resultset rs;  /* and result sets .. */
    ZOOM_options o = ZOOM_options_create ();
	int cantidad;

    //ZOOM_options_set (o, "count", "50");

    /* preferred record syntax */
    ZOOM_options_set (o, "preferredRecordSyntax", "usmarc");
    ZOOM_options_set (o, "elementSetName", "F");
	ZOOM_options_set (o, "databaseName", databaseName);

	/* chequeo si cip_proxy != null agrego la opcion de proxy */

	if (cip_proxy.GetLength()>0)
	{
		ZOOM_options_set (o, "proxy", cip_proxy);

	}


	z = ZOOM_connection_create (o);
	ZOOM_connection_connect (z, host, atoi(port));

	if (ZOOM_connection_error(z,&mensaje,&addinfo))
	{
		
		Log(nametarget+" - "+mensaje,addinfo,cme,searchcode);
		return false;
	}


	Log(nametarget+" - "+tMensaje[45][8]+" "+host+":"+port+"/"+databaseName,"",cme,searchcode);
	Log(nametarget+" - "+tMensaje[45][9]+" "+PQNExpression,"",cme,searchcode);

	rs = ZOOM_connection_search_pqf (z, PQNExpression);

	if (ZOOM_connection_error(z,&mensaje,&addinfo))
	{
		Log(nametarget+" - "+mensaje,addinfo,cme,searchcode);
		return false;
	}

	cantidad = ZOOM_resultset_size(rs);


	CString numero="";
	numero.Format("%d",cantidad);

	CString txt = "";
				
	Log(nametarget+" - "+tMensaje[46][0]+ numero,"",cme,searchcode);
    int pos;

	for (pos = 0; pos < cantidad && pos < limite && !threadfin; pos++)
	{
		int len; /* length of buffer rec */
		const char *rec = ZOOM_record_get ( ZOOM_resultset_record (rs, pos), "raw; charset=marc8,iso-8859-1", &len);

		//AfxMessageBox(rec);
		/* if rec is non-null, we got a record for display */
		if (rec)
		{
				CString xml = ProcesaMarcGlobal(rec,cmi->TagLeader(),isUTF);
				xml+="<9000>1</9000>";
				xml+="<9001>^a"+host+":"+port+"/"+databaseName+"^b"+nametarget+"</9001>";
				xml+="<9010>^a"+searchcode+"</9010>";
				
				zona_critica_1=true;
				long mfn=cmt.IsisRegistroNuevo(xml,false);
				
				int r=IsisRecRead(cmt.ms,0,mfn);
				cmt.IsisDump(miArea,MAXMFRL);
				OemToChar(miArea, miArea);				

				//AfxMessageBox(miArea);
				
				r= IsisRecCopy(cmt.ms,0,cmi->ms,0);
				mfn=cmi->IsisRegistroNuevo(miArea,true);
				zona_critica_1=false;
				
				if (pos%100==0 && pos!=0)
				{
					txt.Format ("%d",pos);
					Log(nametarget+" - # Rec.: "+ txt,"",cme,searchcode);    
					
				}

				txt.Format("%d",pos+1);				

		}
		else
		{
			Log(nametarget+" - "+tMensaje[46][8] ,"",cme,searchcode);
			cmt.IsisFin();	
    		return false;
		}
	}


	numero.Format("%d",pos);
	Log(nametarget+" - "+tMensaje[46][1]+ numero ,"",cme,searchcode);
    cmt.IsisFin();
	
    ZOOM_resultset_destroy (rs);
    ZOOM_connection_destroy (z);
    ZOOM_options_destroy(o);

    return true;
}



UINT YazThreadProc(LPVOID pParam)
{

	thread_ejecucion = true;

	CMainFrame* miPparam = (CMainFrame *) pParam;
	char Area[1024];

	CFileFind f;
	CMyIsisMarcZ cmi;
	CMyIsisMarcZ cme;
	CMyIsisMarcZ cmz;
	CMyIsisMarcZ cmt;


	BOOL estadosalida=false;
	
	AbrirBases(&cmi,&cme,&cmz);
		

	
	int i=1;
	while (!threadfin && i<=cmz.IsisCantRegistros())
	{
			CString cadena="";

			int r = cmz.IsisRegistroLight(i,false);


			if (!threadfin && r>=0)			
			{	
				r = cmz.IsisCampo(7,i,1,Area,1024);

				if (!threadfin && r>0 && atoi(Area)==0)
				{		

					// Intento Bloquear la busqueda y guardo el cambio de estado

					int r = cmz.IsisRegistroLight(i,true);
					while (!threadfin && r==ERR_RECLOCKED)
						r = cmz.IsisRegistroLight(i,true);

					r = cmz.IsisModificarCampo(7,1,"1");
					r = cmz.IsisGuardar(true);
					
					CString miestado = 1;

					// Seteo este estado para saber que tengo que actualizar
					// invertido

					estadosalida = true;

				
					for (int j=1;j<=cmz.IsisCantCampos(4) && !threadfin;j++)
					{
						int r = cmz.IsisSubCampo(4,j,"c",Area,sizeof(Area));
						CString database = Area;
						r = cmz.IsisSubCampo(4,j,"a",Area,1024);
						CString host = Area;
						r = cmz.IsisSubCampo(4,j,"b",Area,1024);
						CString port = Area;
						r = cmz.IsisSubCampo(4,j,"d",Area,1024);						
						CString nametarget = Area;
						r = cmz.IsisSubCampo(4,j,"e",Area,1024);						
						CString UTF = Area;
						
						r = cmz.IsisCampo(6,i,1,Area,1024);
						CString expression = Area;
						r = cmz.IsisCampo(5,i,1,Area,1024);
						CString limite = Area;
						r = cmz.IsisCampo(1,i,1,Area,1024);
						CString codigo = Area;				
						

						int milimite = atoi(limite);

						CString cadena = "";
						cadena.Format ("%d",j);

						CString otra="";
						otra.Format ("%d",cmz.IsisCantCampos(4));


						miPparam->mi_EstadoTexto=tMensaje[45][4]+codigo+" server ("+cadena+":"+otra+")";

						bool isUTF=false;
						if (UTF=="yes")
							isUTF=true;
	
						if (ProcesoBusqueda(host,port,database,expression,milimite,codigo,nametarget,&cmi,&cme,isUTF))
						{
							r = cmz.IsisRegistroLight(i,false);			
							miPparam->mi_EstadoTexto=tMensaje[45][5]+codigo;

							// Si alguna de las busquedas falla, queda en estado fallido
							if (miestado!="9")
								miestado = "2";
							
						}
						else
						{
							miPparam->mi_EstadoTexto=tMensaje[45][6]+codigo;
							miestado = "9";
							
						}

					}

					// A la salida del for vuelvo a intentar bloquear
					// para grabar el estado definitivo de la busqueda

					r=cmz.IsisRegistroLight(i,true); 
					int veces=1;
					while (!threadfin && r==ERR_RECLOCKED && veces++<5)
						r=cmz.IsisRegistroLight(i,true); 

					// Salio sin poder bloquear
					// por tanto elimino thread y espero proxima vuelta

					if (r<0)
					{
						miPparam->mi_EstadoTexto=tMensaje[46][5];
						cmz.IsisFin();
						thread_ejecucion=false;
						miPparam->m_YazThread=NULL;
						AfxEndThread(0);
						return 0;
					}
					else
					{
						r = cmz.IsisModificarCampo(7,1,miestado);
						r = cmz.IsisGuardar(true);						
					}


				}							

			}

			i++;

			//r=cmz.IsisUnlock();
		}


	if (!threadfin)			
	{		
				miPparam->mi_EstadoTexto = tMensaje[45][7];
							
	}

	
	if (estadosalida)
	{
		miPparam->mi_EstadoTexto = tMensaje[49][4];
		ActualizarInvertido(&cmi,&cme);
	}

	CerrarBases(&cmi,&cme,&cmz);	
	thread_ejecucion=false;
	miPparam->m_YazThread=NULL;
	AfxEndThread(0);

	return 0;
}

CString ProcesaMarcGlobal(CString Marc, CString TagLeader, bool UTF=false)
{

	// El leader queda completo en el Tag 3000
	// pruebita con utf8

	char area[MAXMFRL];
	//ConvertirFromUTF8(Marc.GetBuffer(MAXMFRL), area);
	//Marc=area;


	CString xml="<"+TagLeader+">"+Marc.Mid(0,24)+"</"+TagLeader+">";			
	

	int findir = Marc.Find((char)30);


	CString Directorio = Marc.Mid(24,findir-24);

	CString tag;
	CString contenido;
	

	int longitud;
	int inicio;
	

	// Ahora tenemos que armar el mapa para cada uno 
	// de los campos
	int cuentadir=0;
	
	while (cuentadir<Directorio.GetLength())
	{
		tag = Directorio.Mid(cuentadir,3);
		longitud = atoi(Directorio.Mid(cuentadir+3,4));
		inicio = atoi(Directorio.Mid(cuentadir+7,5));
		contenido = Marc.Mid (inicio+Directorio.GetLength()+25,longitud-1);

		if (UTF)
		{
			ConvertirFromUTF8(contenido.GetBuffer(MAXMFRL), area);
			contenido=area;
		}


		contenido.Replace('\x1F','^');
		contenido.Replace('<','[');
		contenido.Replace('>',']');
		xml+="<"+tag+">"+contenido+"</"+tag+">";
	
		//Siguiente entrada del directorio
		cuentadir+=12;
	}

	return xml;
}



CString usuario;
CString basesession;
CString reginicio;
CString globaltoken;
